#include <qlocale.h>
#include <QPalette>
#include <QPixmap>
#include <QBrush>
#include <QWidget>
#include <QTime>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QDir>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QStringConverter>
#include <QRegularExpression>
#include <QRandomGenerator>
#else
#include <QTextCodec>
#include <QRegExp>
#endif
#include <QProcess>
#include <QTranslator>
#include <QDateTime>
#include <stdio.h>
#include <stdlib.h>
#include <QElapsedTimer>
#include <QPixmap>
#include <QPainter>
#include <QTextStream>
#include <QScreen>
#include <QtGui/QtGui>
#include <QDebug>
#include <QFileDialog>
#ifdef Q_OS_UNIX
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#else
#include <windows.h>
#endif
#include "QUIUtils.h"

/**
 * @brief deskWidth 获取桌面宽度
 * @return 返回桌面宽度的整数值
 */
int QUIUtils::deskWidth()
{
    static int width = 0;
    if (width == 0)
    {
        QScreen *screen = QGuiApplication::primaryScreen();
        if (screen) {
            QRect screenGeometry = screen->geometry();
            width = static_cast<int>(screenGeometry.width() * 0.36);
        }
    }

    return width;
}

/**
 * @brief deskHeight 获取桌面高度
 * @return 返回桌面高度的整数值
 */
int QUIUtils::deskHeight()
{
    static int height = 0;
    if (height == 0)
    {
        QScreen *screen = QGuiApplication::primaryScreen();
        if (screen) {
            QRect screenGeometry = screen->geometry();
            height = static_cast<int>(screenGeometry.height() * 0.7);
        }
    }

    return height; // 返回桌面高度的整数值
}


/**
 * @brief appName 程序本身文件名称
 * @return
 */
QString QUIUtils::appName()
{
    return qApp->applicationName();
}

/**
 * @brief appPath 程序当前所在路径
 * @return
 */
QString QUIUtils::appPath()
{

    return qApp->applicationDirPath();
}

/**
 * @brief initRand 初始化随机数种子
 */
void QUIUtils::initRand()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    // Qt 6: Use QRandomGenerator (initialized automatically)
    Q_UNUSED(QRandomGenerator::global());
#else
    QTime t = QTime::currentTime();
    qsrand(static_cast<uint>( t.msec() + t.second() * 1000));
#endif
}

/**
 * @brief newDir 新建目录
 * @param dirName
 */
bool QUIUtils::newDir(const QString &dirName)
{
    bool bRet = false;
    QString strDir = dirName;

    if (!strDir.startsWith("/") && !strDir.contains(":/"))
    {
        strDir = QString("%1/%2").arg(QUIUtils::appPath()).arg(strDir);
    }

    QDir dir(strDir);
    if (!dir.exists())
    {
        bRet = dir.mkpath(strDir);
    }
    else
    {
        bRet = true;
    }
    return bRet;
}

/**
 * @brief removeDir 删除目录及目录下文件
 * @param dirName
 * @return
 */
bool QUIUtils::removeDir(const QString &dirName)
{
    if(dirName.isEmpty())
    {
        return true;
    }

    QDir dir(dirName);
    foreach(QFileInfo mfi, dir.entryInfoList())
    {
        if(!mfi.isFile())
        {
            continue;
        }
        QFile file(mfi.absoluteFilePath());
        file.remove();
        file.close();
    }
    dir.rmdir(dirName);

    return true;
}

/**
 * @brief removeFile 删除文件
 * @param dirName
 * @return
 */
bool QUIUtils::removeFile(const QString &dirName)
{
    QFile file(dirName);
    if(file.exists())
    {
        file.remove();
    }
    return true;
}

/**
 * @brief setBackground 设置背景色
 * @param pixmap
 */
void QUIUtils::setBackground(QWidget* obj, const QString &pixmap)
{
    // 增加背景色
    QPalette mPalette;
    QPixmap mPixmap(pixmap);
    mPalette.setBrush(QPalette::Window, QBrush(mPixmap));
    obj->setPalette(mPalette);
    return;
}

/**
 * @brief setCodec 设置系统编码格式，默认utf-8
 * @param codec
 */
void QUIUtils::setCodec(const char* codec)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QTextCodec *pcodec = QTextCodec::codecForName(codec);
    QTextCodec::setCodecForLocale(pcodec);
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
    QTextCodec::setCodecForCStrings(pcodec);
    QTextCodec::setCodecForTr(pcodec);
#endif
#else
    Q_UNUSED(codec);
    // Qt 6: QTextCodec is deprecated, encoding is UTF-8 by default
#endif
    return;
}

/**
 * @brief sleep 休眠sec毫秒
 * @param sec
 */
void QUIUtils::msleep(const int msec)
{
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while (QTime::currentTime() < dieTime)
    {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
#ifdef Q_OS_UNIX
        struct timeval	timeout ;
        timeout.tv_sec = 0;
        timeout.tv_usec = 500;
        if(select(1, nullptr, nullptr, nullptr, &timeout) == -1)
        {
            struct timespec tv;
            tv.tv_sec = 0;
            tv.tv_nsec = 500 * 1000;
            nanosleep(&tv, nullptr);
        }
#else
        Sleep(100);
#endif
    }
    return;
}

void QUIUtils::delay_ms(int Time, bool IsThread)
{
    if(Time < 0) return;
    QElapsedTimer  tmr;
    tmr.start();
    while(true)
    {
        if(IsThread)
        {
            QCoreApplication::processEvents();
        }
        else
        {
#ifdef Q_OS_UNIX
            msleep(1);
#else
            Sleep(1);
#endif
        }
        if (tmr.elapsed() >= Time)
        {
            break;
        }
    }
}

/**
 * @brief checkIpValid 检测IP是否正确
 * @param ip
 * @return bool
 */
bool QUIUtils::checkIpValid(const QString &ip)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
    QRegularExpression RegExp("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$");
    return RegExp.match(ip).hasMatch();
#else
    QRegExp RegExp("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");
    return RegExp.exactMatch(ip);
#endif
}

/**
 * @brief hexToQString
 * @param pHex
 * @param len
 * @return
 */
QString QUIUtils::hexToQString(unsigned char *pHex, int len)
{
    int index = 0;
    QString mstr = "";

    if(!pHex)
        return "";

    for(index = 0; index < len; index ++)
    {
        mstr = mstr + QString::number(pHex[index], 16) + " ";
    }
    return mstr;
}

/**
 * @brief setStyle 静态加载样式
 * @param style
 */
void QUIUtils::setStyle(QWidget* pObj, const QString &style)
{
    if(!pObj || style.isEmpty())
    {
        return;
    }
    QFile qss(style);
    qss.open(QFile::ReadOnly);
    pObj->setStyleSheet(qss.readAll());
    qss.close();
    return;
}

/**
 * @brief setTranslator 设置翻译文件
 * @param qmFile
 */
void QUIUtils::setTranslator(const QString &qmFile)
{
    QTranslator *trans = new QTranslator(qApp);
    if (trans->load(qmFile)) {
        qApp->installTranslator(trans);
    } else {
        delete trans;
        qWarning() << "Failed to load translation file:" << qmFile;
    }
    return;
}

/**
 * @brief setSystemTime 设置系统时间
 * @param year
 * @param month
 * @param day
 * @param hour
 * @param min
 * @param sec
 */
void QUIUtils::setSystemTime(QString year, QString month,
                             QString day, QString hour,
                             QString min, QString sec)
{
#ifdef Q_OS_WIN
    QProcess p(0);
    p.start("cmd");
    p.waitForStarted();
    p.write(QString("date %1-%2-%3\n")
                .arg(year).arg(month).arg(day).toLatin1());
    p.closeWriteChannel();
    p.waitForFinished(1000);
    p.close();
    p.start("cmd");
    p.waitForStarted();
    p.write(QString("time %1:%2:%3.00\n")
                .arg(hour).arg(min).arg(sec).toLatin1());
    p.closeWriteChannel();
    p.waitForFinished(1000);
    p.close();
#else
    QString cmd = QString("date %1%2%3%4%5.%6")
                      .arg(month).arg(day).arg(hour)
                      .arg(min).arg(year).arg(sec);
    system(cmd.toLatin1());
    system("hwclock -w");
#endif
}

/**
 * @brief byteArrayToHexStr QByteArray转换成hex类型Qstring
 * @param data
 * @return
 */
QString QUIUtils::byteArrayToHexStr(QByteArray data)
{
    (void)data;
    QString temp = "";
    QString hex = data.toHex();

    for (int i = 0; i < hex.length(); i = i + 2)
    {
        temp += hex.mid(i, 2) + " ";
    }

    return temp.trimmed().toUpper();
}

/**
 * @brief isEnglish 判断字符串是否为纯字母
 * @param str
 * @return
 */
bool QUIUtils::isEnglish(QString str)
{
    if(str.isEmpty())
    {
        return false;
    }
    QByteArray ba = str.toLatin1();
    const char *pch = ba.data();
    bool bRet = true;
    while(*pch)
    {
        if((*pch>='A' && *pch<='Z') || (*pch>='a' && *pch<='z'))
        {
        }
        else
        {
            bRet = false;
            break;
        }
        pch++;
    }
    return bRet;
}

/**
 * @brief isNumber 判断字符串是否为纯数字
 * @param str
 * @return
 */
bool QUIUtils::isNumber(QString str)
{
    QByteArray ba = str.toLatin1();
    const char *s = ba.data();
    while(*s && *s>='0' && *s<='9')
    {
        s++;
    }

    if(*s)
    {
        return false;
    }
    return true;
}

/**
 * @brief readCSVFile 读取CSV文件数据
 * @param fileName
 */
QList<QStringList> QUIUtils::readCSVFile(const QString fileName)
{
    QDir dir = QDir::current();
    QFile file(dir.filePath(fileName));
    QList<QStringList> data;
    QStringList item;
    QString line ;
    data.clear();

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        return data;
    }
    QTextStream stream(&file);
    while(!stream.atEnd())
    {
        line = stream.readLine();
        line = line.trimmed();

        if(line.isEmpty())
        {
            break;
        }
        //将读取的每一行用,分割
        item = line.split(',');
        data.append(item);
    }
    file.close();
    return data;
}

QString QUIUtils::fileToBase64(const QString &filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file:" << file.errorString();
        return QString();
    }

    QByteArray fileData = file.readAll();
    file.close();

    QByteArray base64Data = fileData.toBase64();

    return QString(base64Data);
}

bool QUIUtils::moveFile(const QString &sourcePath, const QString &destinationPath)
{
    QFile file(sourcePath);
    if (file.exists())
    {
        if (file.rename(destinationPath))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}


QString QUIUtils::getCurrentTime()
{
    QString currentTimeString = QDateTime::currentDateTime().toString("yyyyMMddhhmmss");
    return currentTimeString;
}

bool QUIUtils::copyFilesRecursively(const QString &sourceDir, const QString &destinationDir)
{
    QDir().mkpath(destinationDir);

    QDir directory(sourceDir);
    const QStringList fileList = directory.entryList(QDir::Files | QDir::NoDotAndDotDot);

    foreach (const QString& file, fileList)
    {
        const QString srcFilePath = sourceDir + "/" + file;
        const QString destFilePath = destinationDir + "/" + file;

        if (!QFile::copy(srcFilePath, destFilePath))
        {
            return false;
        }
    }

    const QStringList subDirList = directory.entryList(QDir::Dirs | QDir::NoDotAndDotDot);

    foreach (const QString& subDir, subDirList)
    {
        const QString srcSubDirPath = sourceDir + "/" + subDir;
        const QString destSubDirPath = destinationDir + "/" + subDir;

        copyFilesRecursively(srcSubDirPath, destSubDirPath);
    }
    return true;
}

bool QUIUtils::deleteDirectory(const QString &dirPath)
{
    QDir dir(dirPath);

    if (!dir.exists())
    {
        return true;
    }

    Q_FOREACH (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
    {
        if (info.isDir())
        {
            if (!deleteDirectory(info.filePath()))
            {
                return false;
            }
        }
        else
        {
            if (!QFile::remove(info.filePath()))
            {
                return false;
            }
        }
    }

    return dir.rmdir(dirPath);
}




QString QUIUtils::getDirectoryPath()
{
    // 创建 QFileDialog 对象
    QFileDialog dialog;
    dialog.setFileMode(QFileDialog::Directory); // 设置对话框模式为选择目录
    dialog.setOption(QFileDialog::ShowDirsOnly); // 仅显示文件夹

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
#endif

    // 打开对话框并获取选择的目录地址
    if (dialog.exec())
    {
        QString selectedDirectory = dialog.selectedFiles().at(0);
        return selectedDirectory;
    }

    return ""; // 用户取消选择或发生错误时返回空字符串
}

bool QUIUtils::writeToFile(const QString &filePath, const QString &content)
{
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "Failed to open file for writing.";
        return false;
    }

    QTextStream stream(&file);
    stream << content;

    file.close();
    return true;
}

void QUIUtils::deleteBackupFiles(const QString &path)
{
    // 确保路径存在且为目录
    QDir dir(path);
    if (!dir.exists()) {
        qWarning() << "Directory does not exist:" << path;
        return;
    }

    // 设置过滤器，只匹配以 "~" 结尾的文件
    QStringList filters;
    filters << "*~";
    dir.setNameFilters(filters);
    dir.setFilter(QDir::Files | QDir::Hidden);  // 仅匹配文件和隐藏文件

    // 获取过滤后的文件列表
    QFileInfoList fileList = dir.entryInfoList();
    for (const QFileInfo &fileInfo : fileList) {
        QString filePath = fileInfo.absoluteFilePath();
        if (!QFile::remove(filePath)) {
           return;
        }
    }
}



